package GtEngine

import (
	"net"
	. "tksLog"
	. "tksStatic"
	"tksTcp"
)

type clientCallback func(net.Conn, uint32, uint32, uint16, []byte)

var gate *tksTcp.TksTcpModule
var clientCmds map[uint16]clientCallback

func init() {
	clientCmds = make(map[uint16]clientCallback)
}

func clientInit(conn net.Conn) {
	clientConnect(conn)
	Debug("new connnect from %s", conn.RemoteAddr().String())
}

func clientReceive(conn net.Conn, from uint32, to uint32, seq uint16, cmd uint16, data []byte) {
	// Debug("Receive data from %s, cmd: %d, data: %s", conn.RemoteAddr().String(), cmd, string(data))
	if to == 0 {
		//发送给自己的消息.
		if cb, ok := clientCmds[cmd]; ok {
			cb(conn, from, to, seq, data)
		}
	} else {
		//根据cmd查找逻辑服务器，如果cmd为0，则转发到指定to的客户端（包括逻辑服务器）
		if cmd == 0 {
			client := FindGateClientById(to)
			if client == nil {
				//client not register
				return
			}
			tksTcp.SendBuffer(client.Conn, from, to, seq, cmd, data)
		} else {
			//find client
			client := FindGateClientByAddr(conn.RemoteAddr().String())
			if client == nil {
				//client not register
				conn.Close()
				return
			}
			//
			server := FindServerByCmd(cmd)
			if server == nil {
				//no this server
				conn.Close()
				return
			}
			tksTcp.SendBuffer(server.Cleint.Conn, client.Id, 0, seq, cmd, data)
		}
	}

}

func clientClose(conn net.Conn) {
	clientDisconnect(conn)
	Debug("client close connect from %s\n", conn.RemoteAddr().String())
}

func RegisterGateCmd(cmd uint16, cb clientCallback) {
	_, ok := clientCmds[cmd]
	if ok {
		return
	} else {
		clientCmds[cmd] = cb
	}
}

func NewGate(port string) error {
	Debug("new gate: %s", port)
	var err error
	gate, err = tksTcp.NewServer(port, clientInit, clientReceive, clientClose)
	if err != nil {
		return err
	}
	return nil
}

func ServerHeartbeat(conn net.Conn, from uint32, to uint32, seq uint16, buf []byte) {
	Debug("recv heartbeat from %s %d", conn.RemoteAddr().String(), from)
	client := FindGateClientByAddr(conn.RemoteAddr().String())
	if client != nil {
		client.Toc <- 0
		//
		sendRsp(conn, 0, 0, seq, CmdGateHeartbeatRsp, RetSucc)
		return
	}
	conn.Close()
}
